package com.dizang.ddd.entity;

import java.io.File;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

public abstract class AbstractPomBuilder {
    
    private static final Logger logger = LoggerFactory.getLogger(AbstractPomBuilder.class);

    abstract protected String getGroupId() ;

    abstract protected String getParentArtifactId() ;

    abstract protected String getArtifactId() ;
    
    abstract protected List<AbstractProjectBuilder> getDependencies();
    
    
    public String getPath() {
        StringBuilder builder = new StringBuilder();
        builder.append("/");
        if (getArtifactId()!=null) {
            builder.append(getArtifactId());
        }
        return builder.toString();
    }
    
    public boolean createPom(String path) {
        try {

            // 创建解析器工厂
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = factory.newDocumentBuilder();
            Document document = db.newDocument();
            // 不显示standalone="no"
            document.setXmlStandalone(true);
            Element project = document.createElement("project");
            project = createPom(document, project);
            document.appendChild(project);

            // 创建TransformerFactory对象
            TransformerFactory tff = TransformerFactory.newInstance();
            // 创建 Transformer对象
            Transformer tf = tff.newTransformer();
            // 输出内容是否使用换行
            tf.setOutputProperty(OutputKeys.INDENT, "yes");
            tf.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, "");
            tf.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
            tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
            // 创建xml文件并写入内容
            tf.transform(new DOMSource(document),
                    new StreamResult(new File(path + this.getPath() + "/" + "pom.xml")));
            logger.info("生成{}/pom.xml成功", getArtifactId());
        } catch (DOMException e) {
            logger.error(e.getMessage(), e);
        } catch (TransformerConfigurationException e) {
            logger.error(e.getMessage(), e);
        } catch (IllegalArgumentException e) {
            logger.error(e.getMessage(), e);
        } catch (ParserConfigurationException e) {
            logger.error(e.getMessage(), e);
        } catch (TransformerFactoryConfigurationError e) {
            logger.error(e.getMessage(), e);
        } catch (TransformerException e) {
            logger.error(e.getMessage(), e);
        }
        return true;

    }
    
    public Element createPom(Document document, Element project) {

        buildTotalNode(document, project);
        buildBaseNode(document, project);
        buildPropertiesNode(document, project);
        buildModuleNode(document, project);
        buildDependenciesNode(document, project);

        return project;

    }

    protected Element buildTotalNode(Document document, Element project) {
        project.setAttribute("xmlns", "http://maven.apache.org/POM/4.0.0");
        project.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
        project.setAttribute("xsi:schemaLocation",
                "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd");
        return project;
    }

    abstract protected Element buildBaseNode(Document document, Element project) ;

    abstract protected Element buildPropertiesNode(Document document, Element project);

    abstract protected Element buildModuleNode(Document document, Element project);

    abstract protected Element buildDependenciesNode(Document document, Element project) ;


}
